package cn.com.connext.scrm.service;

import cn.com.connext.scrm.cache.NoteCache;
import cn.com.connext.scrm.client.MemberClient;
import cn.com.connext.scrm.domain.enumeration.AuditStatus;
import cn.com.connext.scrm.domain.enumeration.DeleteStatus;
import cn.com.connext.scrm.domain.enumeration.MemberStatus;
import cn.com.connext.scrm.domain.master.*;
import cn.com.connext.scrm.repository.master.*;
import cn.com.connext.scrm.service.dto.*;
import cn.com.connext.scrm.service.mapper.BrowseRecordMapper;
import cn.com.connext.scrm.service.mapper.NoteCollectionMapper;
import cn.com.connext.scrm.service.mapper.NoteLikesMapper;
import cn.com.connext.scrm.service.mapper.NoteMapper;
import cn.com.connext.scrm.utils.RedisUtils;
import cn.com.connext.scrm.web.rest.errors.MyErrorCode;
import cn.com.connext.scrm.web.rest.vm.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.connext.common.exception.ServiceException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.persistence.criteria.*;
import javax.persistence.criteria.Order;
import javax.transaction.Transactional;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

/**
 * Created by YANG205 on 2018/6/27.
 */
@Service
@Transactional
public class NoteService extends BaseService<Note, String> {

    private final Logger log = LoggerFactory.getLogger(NoteService.class);

    private final NoteRepository noteRepository;

    @Autowired
    private NoteMapper noteMapper;

    @Autowired
    private NoteLikesMapper noteLikesMapper;

    @Autowired
    private NoteCollectionMapper noteCollectionMapper;

    @Autowired
    private BrowseRecordMapper browseRecordMapper;

    @Autowired
    private NoteLikesRepository noteLikesRepository;

    @Autowired
    private NoteCollectionRepository noteCollectionRepository;

    @Autowired
    private BrowseRecordRepository browseRecordRepository;

    @Autowired
    private MemberRepository memberRepository;

    @Autowired
    private RelationRepository relationRepository;

    @Autowired
    private InteractiveRecordService interactiveRecordService;

    @Autowired
    private TeacherRepository teacherRepository;

    @Autowired
    private NoteTagRepository noteTagRepository;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private DWAUserRepository dwaUserRepository;

    @Autowired
    private DWAUserInfoRepository dwaUserInfoRepository;

    @Autowired
    private MemberClient memberClient;

    @Autowired
    private NoteCache noteCache;

    @Autowired
    private WxAPIService wxAPIService;

    private static final String allHomeNoteKey = "all-home-note-";
    private static final String fineHomeNoteKey = "fine-home-note-";
    private static final String noteDetailKey = "note-detail-";
    private static final long ONE_DAY = 3600 * 24 * 30L ;

    private final static Object REDIS_LOCK1 = new Object();
    private final static Object REDIS_LOCK2 = new Object();
    private final static Object REDIS_LOCK3 = new Object();

    public NoteService(NoteRepository noteRepository) {
        super(noteRepository);
        this.noteRepository = noteRepository;
    }

    public NoteDTO saveNote(Note entity) {
        String searchContent = null;
        log.debug("Request to save {} : {}", getEntityName(), entity);
        UnionIdVM unionIdVM = new UnionIdVM();
        unionIdVM.setUnionId(entity.getUserId());
        log.info("unionId:{}", unionIdVM.getUnionId());
        Member member = memberClient.findMemberByUserId(unionIdVM);
        String memberName = member.getNickName();
        searchContent = memberName;
        String noteContent = entity.getContent();
        searchContent = searchContent + "," + noteContent;
        List<ScoreLogDTO> logDTOList = memberClient.findAllScoreByNoteId(entity.getId());
        String goodName = "";
        for (ScoreLogDTO logDTO : logDTOList){
            WhiskyDTO dto = memberClient.findById(logDTO.getGoodId());
            goodName = goodName + "," + dto.getNameCh();
        }
        if (StringUtils.isNotEmpty(goodName)) {
            searchContent = searchContent + "," + goodName;
        }
        entity.setSearchContent(searchContent);
        entity.setAnswer(false);
        entity = noteRepository.save(entity);
        return noteMapper.toDto(entity);
    }

    /**
     * 发布帖子
     *
     * @param noteVM
     * @return
     */
    public JsonResult saveNoteForWeChat(NoteVM noteVM) {
        JsonResult jsonResult = new JsonResult();
        JSONObject content = wxAPIService.msgSafeCheck(noteVM.getContent());
        log.info("contentCode:{}", content.get("errcode"));
        Integer code = (Integer) content.get("errcode");
        if (code == 0){
            if (StringUtils.isNotEmpty(noteVM.getUserId())) {
                String userId = noteVM.getUserId();
                Member member = memberRepository.findOneByUnionId(userId);
                if (null == member || member.getStatus() == MemberStatus.DELETED) {
                    jsonResult.setState(1);
                    jsonResult.setData(null);
                    jsonResult.setMessage("当前用户不存在!");
                    return jsonResult;
                } else {
                    if (true == member.getBanned()) {
                        jsonResult.setState(1);
                        jsonResult.setData(null);
                        jsonResult.setMessage("您已被禁言，无法发布!");
                        return jsonResult;
                    }
                }
            }
            noteVM.setCreateTime(ZonedDateTime.now());
            //已审核
            noteVM.setAuditStatus(AuditStatus.AUDITED);
            //未删除
            noteVM.setDeleteStatus(DeleteStatus.ACTIVATED);
            //是否转发（该属性目前弃用）
            noteVM.setRepost(noteVM.getRepost() == null ? false : noteVM.getRepost());
            //是否置顶
            noteVM.setIsTop(noteVM.getIsTop() == null ? false : noteVM.getIsTop());
            Note note = noteMapper.toEntity(noteVM);

            if (noteVM.getProductRate() != null && noteVM.getProductRate().size() > 0) {
                note.setRate(true);
            }else {
                note.setRate(false);
            }
            note.setAnswer(false);//设置为帖子
            note = noteRepository.save(note);

            //如有@功能，增加对应的互动记录
            if (StringUtils.isNotEmpty(note.getInviterId())
                && StringUtils.isNotEmpty(note.getUserId())
                && StringUtils.isNotEmpty(note.getId())) {
                String noteId = note.getId();
                String userId = note.getUserId();
                ZonedDateTime createTime = note.getCreateTime();
                List<String> inviterList = Arrays.asList(StringUtils.split(note.getInviterId(), ","));
                if (null != inviterList && inviterList.size() > 0) {
                    for (String inviter : inviterList) {
                        //interactiveRecordService.create(noteId, userId, inviter, 0, 0, createTime);
                        InteractiveRecordDTO interactiveRecordDTO = new InteractiveRecordDTO();
                        interactiveRecordDTO.setNoteId(noteId);
                        interactiveRecordDTO.setContent(note.getTitle());
                        interactiveRecordDTO.setCreateTime(createTime);
                        interactiveRecordDTO.setReceiveUserId(inviter);
                        interactiveRecordDTO.setUserId(userId);
                        interactiveRecordDTO.setInteractiveType(0);
                        interactiveRecordDTO.setLookup(false);
                        interactiveRecordService.createNew(interactiveRecordDTO);
                    }
                }
            }
            if (noteVM.getProductRate() != null && noteVM.getProductRate().size() > 0) {
                for (ScoreLogVM vm: noteVM.getProductRate()){
                    vm.setNoteId(note.getId());
                    WantDrinkVM drinkVM = new WantDrinkVM();
                    drinkVM.setGoodId(vm.getGoodId());
                    drinkVM.setFlag(true);
                    drinkVM.setUnionId(vm.getUserId());
                    drinkVM.setSource("note");
//                drinkVM.setWid(vm.get);
                    memberClient.drink(drinkVM);
                }
                ResponseEntity responseEntity = memberClient.saveScore(noteVM.getProductRate());
//            Note note1 = noteRepository.findOne(note.getId());
//            note.setRate(true);
//            noteRepository.save(note);
            }
//        noteCache.refreshCache();
            jsonResult.setState(0);
            jsonResult.setData(note);
            jsonResult.setMessage("发布成功!");
            return jsonResult;
        }else {
            jsonResult.setState(1);
            jsonResult.setMessage("内容中包含敏感词，请修改");
            return jsonResult;
        }
    }

    /**
     * 获取某个帖子信息(后台管理)
     * Get one note by id.
     *
     * @param id the id of the entity
     * @return the entity
     */
    public NoteDTO findOneDTO(String id, String unionId) {
        log.debug("Request to get Note : {}", id);
        Note note = noteRepository.findOne(id);
        if (null == note || DeleteStatus.DELETED == note.getDeleteStatus()) {
            throw new ServiceException(MyErrorCode.ERROR_NOTE_NOT_EXIST);
        } else {
            NoteDTO noteDTO = noteMapper.toDto(note);
            return noteDTO;
        }
    }

    /**
     * 获取某个帖子信息(小程序)
     * Get one note by id.
     *
     * @param id the id of the entity
     * @return the entity
     */
    public NoteDTO findOneDTOForWeChat(String id, String unionId) {
        log.debug("Request to get Note : {}", id);
        Note note = noteRepository.findOne(id);
        if (null == note || DeleteStatus.DELETED == note.getDeleteStatus()) {
            throw new ServiceException(MyErrorCode.ERROR_NOTE_NOT_EXIST);
        } else {
//            String key = noteDetailKey + id;
//            if (redisUtils.exists(key)){
//                NoteDTO dto = (NoteDTO) redisUtils.get(key);
//                return dto;
//            }
            NoteDTO noteDTO = noteMapper.toDto(note);
            List<ScoreLogDTO> scoreLogDTOList = memberClient.findAllScoreByNoteId(note.getId());
            for (ScoreLogDTO dto : scoreLogDTOList){
                WhiskyDTO whiskyDTO = memberClient.findById(dto.getGoodId());
                dto.setWhiskyDTO(whiskyDTO);
            }
            noteDTO.setScoreLogDTOList(scoreLogDTOList);
            //回传界面上的more
            if (null != note.getContent()) {
                if (note.getContent().length() > 75) {
                    noteDTO.setMore(false);
                } else {
                    noteDTO.setMore(true);
                }
            } else {
                noteDTO.setMore(false);
            }

            //邀请回答的人的nickName
            List<String> invitor = new ArrayList<>();
            if (StringUtils.isNotEmpty(note.getInviterId())) {
                List<String> invitorList = Arrays.asList(StringUtils.split(note.getInviterId(), ","));
                for (String str : invitorList) {
                    Member member = memberRepository.findOneByUnionId(str);
                    if (null != member && StringUtils.isNotEmpty(member.getNickName())) {
                        invitor.add(member.getNickName());
                    }
                }
                noteDTO.setInviterList(invitor);
            } else {
                noteDTO.setInviterList(invitor);
            }
//            redisUtils.set(key, noteDTO, ONE_DAY);

            return noteDTO;
        }
    }

    /**
     * 删除帖子
     *
     * @param id
     * @return
     */
    public void deleteNote(String id) {
        log.debug("Request to delete Note : {}", id);
        Note note = noteRepository.findOne(id);
        if (null != note) {
            note.setDeleteStatus(DeleteStatus.DELETED);
            //清除该互动记录的未回答状态
            interactiveRecordService.deleteInteractiveRecordByNoteId(id);
        }
        NoteIdVM vm = new NoteIdVM();
        vm.setNoteId(id);
        memberClient.deleteScoreByNoteId(vm);
        noteRepository.save(note);
        String key = noteDetailKey + id;
        redisUtils.remove(key);

    }


    /**
     * @param pageable    分页参数
     * @param auditStatus 审核状态
     * @param title       帖子标题
     * @param nickName    发帖人姓名
     * @param keyWord     搜索栏的关键字
     * @param columnType  分栏类型（0：所有 1：关注 2：品饮笔记 3：问答 4：DWA圈子）
     * @param unionId     当前用户小程序的UnionID
     * @return
     */
    public Page<NoteDTO> getAllUnDeletedNote(Pageable pageable, String keyWord, Integer columnType, String unionId, String nickName, AuditStatus auditStatus, String title) {
        List<Note> noteList = new ArrayList<Note>();
        NoteDTO noteDTO = new NoteDTO();

        ///所有被删除的会员UnionId的集合
        List<String> unionIdList = new ArrayList<String>();
        unionIdList = memberRepository.findUnionIdWithoutUse();

        //region 小程序查询
        if (null != columnType) {
            noteDTO.setAuditStatus(AuditStatus.AUDITED);
            //noteDTO.setDeleteStatus(DeleteStatus.ACTIVATED);
            switch (columnType) {
                //所有帖子---帖子状态未删除+发帖人状态未删除
                case 0:
                    noteList = noteRepository.findAll(getWhereClause(noteDTO, null, unionIdList));
                    break;
                //关注
                case 1:
                    if (StringUtils.isNotEmpty(unionId)) {
                        //region 后台管理查询
                        ///用于存放模糊查询的
                        List<String> stringList = new ArrayList<>();
                        if (null == unionId) {
                            noteDTO.setTitle(title);
                            noteDTO.setNickName(nickName);
                            noteDTO.setRepost(false);
                            if (auditStatus.equals("UNAUDITED")) {
                                noteDTO.setAuditStatus(AuditStatus.UNAUDITED);
                            }
                            if (auditStatus.equals("AUDITED")) {
                                noteDTO.setAuditStatus(AuditStatus.AUDITED);
                            }
                            if (StringUtils.isNotEmpty(nickName)) {
                                stringList = memberRepository.findAllUnionIdByNickNameLike(nickName);
                                stringList.removeAll(unionIdList);
                                Page<Note> result = noteRepository.findAll(getWhereClause(noteDTO, stringList, null), pageable);
                                return result.map(note -> noteMapper.toDto(note));
                            } else {
                                Page<Note> result = noteRepository.findAll(getWhereClause(noteDTO, null, unionIdList), pageable);
                                return result.map(note -> noteMapper.toDto(note));
                            }
                        }
                        //endregion
                        //Member member = memberRepository.findOneByUnionId(unionId);
                        stringList = relationRepository.findFollowIdByUserId(unionId);
                        if (stringList.size() > 0) {
                            stringList.removeAll(unionIdList);
                            if (0 == stringList.size()) {
                                //noteList = null;
                            } else {
                                noteList = noteRepository.findAll(getWhereClause(noteDTO, stringList, null));
                            }
                        } else {
                            //noteList = null;
                        }
                    }
                    break;
                //品饮笔记
                case 2:
                    noteDTO.setNoteType(0);
                    noteList = noteRepository.findAll(getWhereClause(noteDTO, null, unionIdList));
                    break;
                //问答
                case 3:
                    noteDTO.setNoteType(1);
                    noteList = noteRepository.findAll(getWhereClause(noteDTO, null, unionIdList));
                    break;
                //DWA圈子
                default:
                    ///所有DWA学员手机号码的集合
                    List<String> mobileList = new ArrayList<>();
                    //mobileList = studentRepository.findAllMobile();
                    mobileList = dwaUserRepository.findAllMobile();

                    ///所有DWA教师手机号码的集合
                    List<String> mobileList1 = new ArrayList<>();
                    mobileList1 = teacherRepository.findAllMobile();

                    ///所有已经认证的DWA会员(即Student、Teacher表中的手机号码存在于Member表中)的unionId集合
                    List<String> finalList = new ArrayList<>();

                    //所有未删除的用户
                    List<Member> members = memberRepository.findAllByStatus(MemberStatus.ACTIVATED);

                    mobileList.addAll(mobileList1);
                    if (null != members && members.size() > 0) {
                        for (Member member : members) {
                            if (StringUtils.isNotEmpty(member.getMobile())) {
                                if (null != mobileList && mobileList.contains(member.getMobile())) {
                                    finalList.add(member.getUnionId());
                                }
                            }
                        }
                    }

                    noteList = noteRepository.findAll(getWhereClause(noteDTO, finalList, null));
                    break;
            }
        } else {
            //后台列表
            noteDTO.setAuditStatus(auditStatus);
            noteDTO.setTitle(title);
            if (nickName != null) {
                List<String> stringList = memberRepository.findAllUnionIdByNickNameLike(nickName);
                stringList.removeAll(unionIdList);
                Page<Note> result = noteRepository.findAll(getWhereClause(noteDTO, stringList, null), pageable);
                return result.map(note -> noteMapper.toDto(note));
            }
            Page<Note> result = noteRepository.findAll(getWhereClause(noteDTO, null, unionIdList), pageable);
            return result.map(note -> noteMapper.toDto(note));
        }

        if (StringUtils.isNotEmpty(keyWord)) {
            //开始进行关键字匹配
            noteList = filterByKeyword(noteList, keyWord);
        }

        List<Note> newResult = new ArrayList<Note>();
        List<NoteDTO> noteDTOList = new ArrayList<NoteDTO>();
        //region 判断是否关注,是否点赞，是否收藏
//        noteDTOList = addStatus(noteList, unionId);
        //endregion

        //region开始进行分页
        int currIdx = (pageable.getPageNumber() > 0 ? pageable.getPageNumber() * pageable.getPageSize() : 0);
        for (int i = 0; i < pageable.getPageSize() && i < noteList.size() - currIdx; i++) {
            Note report = noteList.get(currIdx + i);
            newResult.add(report);
        }
        noteDTOList = addStatus(newResult, unionId);
        Pageable pageable2 = new PageRequest(pageable.getPageNumber(), pageable.getPageSize());
        Page pageResult = new PageImpl(noteDTOList, pageable2, noteList.size());

        Page<NoteDTO> notePage = pageResult;

        return notePage;
        //endregion

        //endregion
    }


    /**
     * 查询性能优化
     *
     * @param lastIndex  分页参数：上次获取最小index
     * @param pageSize   分页参数：请求条数
     * @param keyWord    搜索栏的关键字
     * @param columnType 分栏类型（0：所有 1：关注 2：品饮笔记 3：问答 4：DWA圈子）
     * @param unionId    当前用户小程序的UnionID
     * @return
     */
    public Page<NoteDTO> getNotes4Wechat(Long lastIndex, Integer pageSize, String keyWord, Integer columnType, String unionId, Boolean isTop) {
        List<String> stringList = null;
        Integer noteType = null;

        switch (columnType) {
            case 1:
                if (StringUtils.isNotEmpty(unionId)) {
                    stringList = relationRepository.findFollowIdByUserId(unionId);
                }
                break;
            case 2:
                noteType = 0;
                break;
            case 3:
                noteType = 1;
                break;
            case 4:
                ///所有DWA教师手机号码的集合
                List<String> mobileList = new ArrayList<>();
                mobileList = this.getTeacherMobileList();

                stringList = this.getUnionIdsByMobiles(mobileList);
                List<String> studentIds = this.getStudentUnionIdList();
                stringList.addAll(studentIds);
                break;
        }

        //region开始进行分页
        Pageable pageable = new PageRequest(0, pageSize);
        Specification<Note> query = getWhereClause4Wechat(lastIndex, noteType, keyWord, stringList, isTop);
//        query.
        Page<Note> result = noteRepository.findAll(query, pageable);

        Page<NoteDTO> t = result.map(note -> noteMapper.toDto(note));
        addStatus2(t, unionId);
        return t;
    }

    public List<String> getStudentUnionIdList() {
        List<String> result = null;
        String redisKey = "StudentUnionIdList";
        Object banners = redisUtils.get(redisKey);
        if (banners != null && banners instanceof List) {
            result = (List<String>) banners;
        }
        if (result == null) {
            synchronized (REDIS_LOCK1) {
                result = dwaUserInfoRepository.findAllUnionId();
                if (result == null) {
                    result = new ArrayList<>();
                }
                redisUtils.set(redisKey, result, 300L);
            }
        }
        return result;
    }

    public List<String> getTeacherMobileList() {
        List<String> result = null;
        String redisKey = "TeacherMobileList";
        Object banners = redisUtils.get(redisKey);
        if (banners != null && banners instanceof List) {
            result = (List<String>) banners;
        }
        if (result == null) {
            synchronized (REDIS_LOCK2) {
                result = teacherRepository.findAllMobile();
                if (result == null) {
                    result = new ArrayList<>();
                }
                redisUtils.set(redisKey, result, 1200L);
            }
        }
        return result;
    }

    public List<String> getUnionIdsByMobiles(List<String> mobileList) {
        List<String> result = null;
        String redisKey = "DWAUnionIdList";
        Object banners = redisUtils.get(redisKey);
        if (banners != null && banners instanceof List) {
            result = (List<String>) banners;
        }
        if (result == null) {
            synchronized (REDIS_LOCK3) {
                result = memberRepository.findUnionIdByMobileAndStatus(mobileList, MemberStatus.ACTIVATED);
                if (result == null) {
                    result = new ArrayList<>();
                }
                redisUtils.set(redisKey, result, 300L);
            }
        }
        return result;
    }

    /**
     * 小程序获取推荐的帖子
     *
     * @param pageable
     * @param keyWord
     * @param unionId
     * @return
     */
    public Page<NoteDTO> getRecommendedNotes(Pageable pageable, String keyWord, String unionId) {
        ///所有DWA教师手机号码的集合
        List<String> mobileList1 = teacherRepository.findAllMobile();

        if (StringUtils.isNotEmpty(unionId)) {
            Member member = memberRepository.findOneByUnionId(unionId);
            if (null != member) {
                if (StringUtils.isNotEmpty(member.getMobile())) {
                    mobileList1.remove(member.getMobile());
                }
            }
        }
        List<String> memberUnionIds = new ArrayList<>();
        if (!CollectionUtils.isEmpty(mobileList1)) {
            ///所有已经认证的DWA会员(Teacher表中的手机号码存在于Member表中)的集合
            memberUnionIds = memberRepository.findUnionIdByMobileAndStatus(mobileList1, MemberStatus.ACTIVATED);
        }
        ///所有已经认证的BA导师的unionId集合
//        List<String> teacher = new ArrayList<>();
//
//        if (null != members && members.size() > 0) {
//            for (Member member : members) {
//                if (StringUtils.isNotEmpty(member.getMobile())) {
//                    if (null != mobileList1 && mobileList1.contains(member.getMobile())) {
//                        teacher.add(member.getUnionId());
//                    }
//                }
//            }
//        }
        NoteDTO noteDTO = new NoteDTO();
        noteDTO.setAuditStatus(AuditStatus.AUDITED);

        List<Note> noteList = new ArrayList<Note>();
        List<Note> newResult = new ArrayList<>();
        if (!CollectionUtils.isEmpty(memberUnionIds)) {
            noteList = noteRepository.findAll(getWhereClause(noteDTO, memberUnionIds, null));
        }
        if (StringUtils.isNotEmpty(keyWord)) {
            //开始进行关键字匹配
            noteList = filterByKeyword(noteList, keyWord);
        }


        //region开始进行分页
        int currIdx = (pageable.getPageNumber() > 0 ? pageable.getPageNumber() * pageable.getPageSize() : 0);
        for (int i = 0; i < pageable.getPageSize() && i < noteList.size() - currIdx; i++) {
            Note report = noteList.get(currIdx + i);
            newResult.add(report);
        }
        //判断是否关注,是否点赞，是否收藏
        List<NoteDTO> noteDTOList = addStatus(newResult, unionId);
        Pageable pageable2 = new PageRequest(pageable.getPageNumber(), pageable.getPageSize());
        Page pageResult = new PageImpl(noteDTOList, pageable2, noteDTOList.size());

        Page<NoteDTO> notePage = pageResult;

        return notePage;
    }

    /**
     * 小程序帖子首页根据关键字搜索
     *
     * @param list
     * @param keyWord
     * @return
     */
    public List<Note> filterByKeyword(List<Note> list, String keyWord) {
        List<Note> res = new ArrayList<>();
        if (null != keyWord && keyWord.length() != 0) {
            //标题匹配
            List<Note> temp_title = new ArrayList<>();
            for (Note note : list) {
                if (null != note.getTitle() && note.getTitle().contains(keyWord)) {
                    temp_title.add(note);
                    res.add(note);
                }
            }
            list.removeAll(temp_title);
            //内容匹配
            List<Note> temp_content = new ArrayList<>();
            for (Note note : list) {
                if (null != note.getContent() && note.getContent().contains(keyWord)) {
                    temp_content.add(note);
                    res.add(note);
                }
            }
            list.removeAll(temp_content);
            //标签匹配
            List<Note> temp_tag = new ArrayList<>();
            for (Note note : list) {
                if (null != note.getTag() && note.getTag().contains(keyWord)) {
                    temp_tag.add(note);
                    res.add(note);
                }
            }
            //list.removeAll(temp_tag);

            if (null != res) {
                return res;
            } else {
                return list;
            }
        } else {
            return list;
        }
    }


    /**
     * 动态生成查询条件
     *
     * @param noteDTO
     * @param stringList1---unionId(IN)
     * @param stringList2---unionId(NOT IN)
     * @return
     */
    private Specification<Note> getWhereClause(final NoteDTO noteDTO, List<String> stringList1, List<String> stringList2) {
        Specification<Note> specification = (Root<Note> root, CriteriaQuery<?> query,
                                             CriteriaBuilder cb) -> {
            List<Predicate> predicates = new ArrayList<Predicate>();
            Predicate lineFactoryLike = cb.notEqual(root.get("deleteStatus"), DeleteStatus.DELETED);
            predicates.add(lineFactoryLike);
            if (!CollectionUtils.isEmpty(stringList1)) {
                CriteriaBuilder.In<String> in = cb.in(root.get("userId"));
                for (String id : stringList1) {
                    in.value(id);
                }
                predicates.add(in);
            }
            if (!CollectionUtils.isEmpty(stringList2)) {
                Predicate lineFactoryNotIn_add = cb.not(root.get("userId").in(stringList2));
                predicates.add(lineFactoryNotIn_add);
            }
            if (null != noteDTO.getNoteType()) {
                Predicate lineFactoryEqual_add = cb.equal(root.get("noteType"), noteDTO.getNoteType());
                predicates.add(lineFactoryEqual_add);
            }
            if (StringUtils.isNotEmpty(noteDTO.getTitle())) {
                List<Predicate> orPredicates = new ArrayList<Predicate>();
                Expression<Integer> p1 = cb.locate(root.get("title"),  noteDTO.getTitle());
                orPredicates.add(cb.or(cb.greaterThan(p1, 0)));
                Expression<Integer> p2 = cb.locate(root.get("content"), noteDTO.getTitle());
                orPredicates.add(cb.or(cb.greaterThan(p2, 0)));
                Predicate p = cb.or(orPredicates.toArray(new Predicate[orPredicates.size()]));
                predicates.add(p);
            }
            if (noteDTO.getAuditStatus() == AuditStatus.UNAUDITED) {
                Predicate lineFactoryEqual_add = cb.equal(root.get("auditStatus"), AuditStatus.UNAUDITED);
                predicates.add(lineFactoryEqual_add);
            }
            if (noteDTO.getAuditStatus() == AuditStatus.AUDITED) {
                Predicate lineFactoryEqual_add = cb.equal(root.get("auditStatus"), AuditStatus.AUDITED);
                predicates.add(lineFactoryEqual_add);
            }
            if (null != noteDTO.getRepost() && false == noteDTO.getRepost()) {
                Predicate lineFactoryEqual_add = cb.equal(root.get("isRepost"), noteDTO.getRepost());
                predicates.add(lineFactoryEqual_add);
            }
            query.orderBy(cb.desc(root.get("isTop").as(Boolean.class)), cb.desc(root.get("createTime").as(ZonedDateTime.class)));
            Predicate[] ps = new Predicate[predicates.size()];
            return cb.and(predicates.toArray(ps));
        };
        return specification;
    }

    /**
     * 动态生成查询条件
     *
     * @param lastIndex----上次获取的最小index
     * @param noteType---0：品饮笔记，1：问答
     * @param keyWord---关键字
     * @param userList---用户（userId）列表
     * @return
     */
    private Specification<Note> getWhereClause4Wechat(Long lastIndex, Integer noteType, String keyWord, List<String> userList, Boolean isTop) {
        Specification<Note> specification = (Root<Note> root, CriteriaQuery<?> query,
                                             CriteriaBuilder cb) -> {
            List<Predicate> predicates = new ArrayList<Predicate>();

            int isTopNum = 1;
            if (isTop) {
                isTopNum = 2;
            }
            Predicate isTopLess = cb.lessThan(root.get("isTop"), isTopNum);
            predicates.add(isTopLess);
            if (lastIndex > 0) {
                Predicate indexLike_add = cb.lessThan(root.get("createdIndex"), lastIndex);
                predicates.add(indexLike_add);
            }
            Predicate lineFactoryLike = cb.equal(root.get("deleteStatus"), DeleteStatus.ACTIVATED);
            Predicate lineFactoryEqual_add = cb.equal(root.get("auditStatus"), AuditStatus.AUDITED);
            predicates.add(lineFactoryEqual_add);
            predicates.add(lineFactoryLike);
            if (noteType != null) {
                predicates.add(cb.equal(root.get("noteType"), noteType));
            }
            if (!CollectionUtils.isEmpty(userList)) {
                CriteriaBuilder.In<String> in = cb.in(root.get("userId"));
                for (String id : userList) {
                    in.value(id);
                }
                predicates.add(in);
            }

            if (StringUtils.isNotEmpty(keyWord)) {
                //List<Predicate> orPredicates = new ArrayList<Predicate>();
                Predicate titleLike_add = cb.like(root.get("title"), "%" + keyWord + "%");
//                orPredicates.add(titleLike_add);
                Predicate contentLike_add = cb.like(root.get("content"), "%" + keyWord + "%");
//                orPredicates.add(contentLike_add);
                Predicate tagLike_add = cb.like(root.get("tag"), "%" + keyWord + "%");
//                orPredicates.add(tagLike_add);
                Predicate or = cb.or(titleLike_add, contentLike_add, tagLike_add);
                predicates.add(or);
            }

//            query.orderBy(cb.desc(root.get("isTop").as(Boolean.class)));
//            query.orderBy(cb.desc(root.get("createdIndex").as(Long.class)));
            List<Order> orderList = new ArrayList<Order>();
            orderList.add(cb.desc(root.get("isTop").as(Boolean.class)));
            orderList.add(cb.desc(root.get("createdIndex").as(Long.class)));
            query.orderBy(orderList);
            Predicate[] ps = new Predicate[predicates.size()];
            return cb.and(predicates.toArray(ps));
        };
        return specification;
    }

    /**
     * 审核帖子
     *
     * @param id
     */
    public Boolean reviewNote(String id) {
        log.debug("Request to review Note : {}", id);
        Note note = noteRepository.findOne(id);
        if (null != note) {
            if (AuditStatus.AUDITED == AuditStatus.AUDITED) {
                throw new ServiceException(MyErrorCode.ERROR_NOTE_HASAUDITED);
            }
            note.setAuditStatus(AuditStatus.AUDITED);
            note.setUpdateTime(ZonedDateTime.now());
            noteRepository.save(note);
            return true;
        } else {
            return false;
        }
    }

    /**
     * 帖子点赞
     *
     * @param noteId
     * @param userId
     * @return
     */
    @Async
    public void likeNote(String noteId, String userId) {

        if (StringUtils.isNotEmpty(userId)) {
            Member member = memberRepository.findOneByUnionId(userId);
            if (null == member || member.getStatus() == MemberStatus.DELETED) {
                throw new ServiceException(MyErrorCode.ERROR_MEMBER_NOT_EXIST);
            } else {
                if (true == member.getBanned()) {
                    throw new ServiceException(MyErrorCode.ERROR_MEMBER_IS_BAN);
                }
            }
        }
        Note note = noteRepository.findOne(noteId);
        if (null == note || DeleteStatus.DELETED == note.getDeleteStatus()) {
            throw new ServiceException(MyErrorCode.ERROR_DATA_ISNULL);
        }
        NoteLikes noteLikes = noteLikesRepository.findOneByNoteIdAndUserId(noteId, userId);
        if (null == noteLikes) {
            log.info("当前行为是点赞");
            NoteLikesDTO noteLikesDTO = new NoteLikesDTO();
            noteLikesDTO.setNoteId(noteId);
            noteLikesDTO.setUserId(userId);
            noteLikesDTO.setCreateTime(ZonedDateTime.now());
            NoteLikes newNoteLikes = noteLikesMapper.toEntity(noteLikesDTO);
            log.info("NoteLikes:{}", JSON.toJSONString(newNoteLikes));
            newNoteLikes = noteLikesRepository.save(newNoteLikes);
            InteractiveRecordDTO interactiveRecordDTO = new InteractiveRecordDTO();
            interactiveRecordDTO.setReceiveUserId(note.getUserId());
            interactiveRecordDTO.setNoteId(noteId);
            interactiveRecordDTO.setCreateTime(newNoteLikes.getCreateTime());
            interactiveRecordDTO.setUserId(userId);
            interactiveRecordDTO.setInteractiveType(2);
            interactiveRecordDTO.setLookup(false);
            String content = note.getContent();
            if (content.length() > 10){
                content = content.substring(0,10)+"...";
            }
            interactiveRecordDTO.setContent(content);
            log.info("interactiveRecordDTO:{}", JSON.toJSONString(interactiveRecordDTO));
            interactiveRecordService.createNew(interactiveRecordDTO);
            noteCache.refreshDetailCacheById(noteId);
            log.info("点赞成功,刷新缓存");
        } else {
            log.info("当前行为是取消点赞");
            noteLikesRepository.delete(noteLikes);
            interactiveRecordService.delete(noteId, userId, note.getUserId(), 2);
            noteCache.refreshDetailCacheById(noteId);
            log.info("取消点赞成功,刷新缓存");
        }
    }

    /**
     * 收藏帖子
     *
     * @param noteId
     * @param userId
     * @return
     */
    public JsonResult collectNote(String noteId, String userId) {
        JsonResult jsonResult = new JsonResult();

        if (StringUtils.isNotEmpty(userId)) {
            Member member = memberRepository.findOneByUnionId(userId);
            if (null == member || member.getStatus() == MemberStatus.DELETED) {
                jsonResult.setState(1);
                jsonResult.setData(null);
                jsonResult.setMessage("当前用户不存在!");
                return jsonResult;
            } else {
                if (true == member.getBanned()) {
                    jsonResult.setState(1);
                    jsonResult.setData(null);
                    jsonResult.setMessage("您已被禁言!");
                    return jsonResult;
                }
            }
        }
        Note note = noteRepository.findOne(noteId);
        if (null == note || DeleteStatus.DELETED == note.getDeleteStatus()) {
            jsonResult.setState(1);
            jsonResult.setData(null);
            jsonResult.setMessage("帖子不存在!");
            return jsonResult;
        } else {
            if (StringUtils.isNotEmpty(note.getUserId()) && note.getUserId().equals(userId)) {
                jsonResult.setState(1);
                jsonResult.setData(null);
                jsonResult.setMessage("无法收藏自己的帖子!");
                return jsonResult;
            }
        }
        NoteCollection noteCollection = noteCollectionRepository.findOneByNoteIdAndUserId(noteId, userId);
        if (null == noteCollection) {
            NoteCollectionDTO noteCollectionDTO = new NoteCollectionDTO();
            noteCollectionDTO.setNoteId(noteId);
            noteCollectionDTO.setUserId(userId);
            noteCollectionDTO.setCreateTime(ZonedDateTime.now());
            NoteCollection newNoteCollection = noteCollectionMapper.toEntity(noteCollectionDTO);
            noteCollectionRepository.save(newNoteCollection);
            noteCache.refreshDetailCacheById(noteId);
            jsonResult.setState(0);
            jsonResult.setData(null);
            jsonResult.setMessage("收藏成功!");
            return jsonResult;
        } else {
            noteCollectionRepository.delete(noteCollection);
            noteCache.refreshDetailCacheById(noteId);
            jsonResult.setState(0);
            jsonResult.setData(null);
            jsonResult.setMessage("取消收藏成功!");
            return jsonResult;
        }
    }

    /**
     * 转发帖子
     *
     * @param noteId
     * @param userId
     * @param authorId
     * @return
     */
    public String repostNote(String noteId, String userId, String authorId) {
        if (StringUtils.isNotEmpty(userId)) {
            Member member = memberRepository.findOneByUnionId(userId);
            if (null == member) {
                return "转发失败！";
            } else {
                if (true == member.getBanned()) {
                    return "您已被禁言，无法转发！";
                }
            }
        }
        Note note = noteRepository.findOne(noteId);
        if (null == note) {
            return "转发失败！";
        } else {
            if (StringUtils.isNotEmpty(note.getUserId()) && note.getUserId().equals(userId)) {
                return "无法转发自己的帖子！";
            }

            NoteVM noteVM = new NoteVM();
            noteVM.setRepost(true);
            noteVM.setOriginalId(note.getId());
            noteVM.setAuthorId(authorId);
            noteVM.setCreateTime(ZonedDateTime.now());
            noteVM.setAuditStatus(AuditStatus.AUDITED);
            noteVM.setDeleteStatus(DeleteStatus.ACTIVATED);
            noteVM.setUserId(userId);
            noteVM.setTitle(note.getTitle());
            noteVM.setContent(note.getContent());
            noteVM.setNoteType(note.getNoteType());
            //帖子图片url集合
            if (StringUtils.isNotEmpty(note.getImgUrl())) {
                List<String> list_imgUrl = Arrays.asList(StringUtils.split(note.getImgUrl(), ","));
                noteVM.setImgUrlList(list_imgUrl);
            }
            //帖子标签集合
            if (StringUtils.isNotEmpty(note.getTag())) {
                JSONArray list_tag = JSONArray.parseArray("[" + note.getTag() + "]");

                noteVM.setNoteTagList(list_tag);
            }
            //帖子邀请回答人集合
            if (StringUtils.isNotEmpty(note.getInviterId())) {
                List<String> list_inviterId = Arrays.asList(StringUtils.split(note.getInviterId(), ","));
                noteVM.setInviterList(list_inviterId);
            }

            Note newNote = noteMapper.toEntity(noteVM);
            noteRepository.save(newNote);
            return "转发帖子成功！";
        }
    }

    /**
     * 浏览帖子
     *
     * @param noteId
     * @param userId
     * @return
     */
    public Boolean browseNote(String noteId, String userId) {
        Note note = noteRepository.findOne(noteId);
        if (null == note) {
            throw new ServiceException(MyErrorCode.ERROR_NOTE_NOT_EXIST);
        } else {
            BrowseRecordDTO browseRecordDTO = new BrowseRecordDTO();
            browseRecordDTO.setUserId(userId);
            browseRecordDTO.setNoteId(noteId);
            browseRecordDTO.setCreateTime(ZonedDateTime.now());
            BrowseRecord browseRecord = browseRecordMapper.toEntity(browseRecordDTO);
            browseRecordRepository.save(browseRecord);
            return true;
        }
    }

    /**
     * 我发布的笔记/问答
     *
     * @param pageable
     * @param userId
     * @param noteType
     * @return
     */
    public Page<NoteDTO> getMyNotes(Pageable pageable, String userId, Integer noteType) {
        List<Note> noteList = noteRepository.findAllWithoutDelete(userId, noteType);
        if (null == noteList) {
            List<NoteDTO> noteDTOList = new ArrayList<NoteDTO>();
            Page<NoteDTO> noteDTOPage = new PageImpl(noteDTOList, pageable, 0);
            return noteDTOPage;
        } else {
//            List<NoteDTO> noteDTOList = new ArrayList<NoteDTO>();
//            noteDTOList = addStatus(noteList, userId);

            List<NoteDTO> noteDTOList = new ArrayList<NoteDTO>();
            List<Note> newResult = new ArrayList<>();
            //region开始进行分页
            int currIdx = (pageable.getPageNumber() > 0 ? pageable.getPageNumber() * pageable.getPageSize() : 0);
            for (int i = 0; i < pageable.getPageSize() && i < noteList.size() - currIdx; i++) {
                Note report = noteList.get(currIdx + i);
                newResult.add(report);
            }
            noteDTOList = addStatus(newResult, userId);
            for (NoteDTO dto: noteDTOList){
                String noteId = dto.getId();
                List<ScoreLogDTO> scoreLogDTOList = memberClient.findAllScoreByNoteId(noteId);
                log.info("查询评分列表返回结果:{}", scoreLogDTOList);
                if (scoreLogDTOList.size() > 0){
                    for (ScoreLogDTO logDTO : scoreLogDTOList){
                        WhiskyDTO whiskyDTO = memberClient.findById(logDTO.getGoodId());
                        log.info("查询酒品详情返回结果:{}", whiskyDTO);
                        if (whiskyDTO != null){
                            logDTO.setWhiskyDTO(whiskyDTO);
                        }
                    }
                }
                dto.setScoreLogDTOList(scoreLogDTOList);
            }
            Pageable pageable2 = new PageRequest(pageable.getPageNumber(), pageable.getPageSize());
            Page pageResult = new PageImpl(noteDTOList, pageable2, noteList.size());
            Page<NoteDTO> notePage = pageResult;

            return notePage;
            //endregion
        }
    }

    /**
     * 我的收藏
     *
     * @param pageable
     * @param userId
     * @return
     */
    public Page<NoteDTO> getMyNoteCollection(Pageable pageable, String userId) {
        List<String> noteIdList = noteCollectionRepository.findNoteIdByUserId(userId);
        //收藏为空
        if (0 == noteIdList.size()) {
            List<NoteDTO> noteDTOList = new ArrayList<NoteDTO>();
            Page<NoteDTO> noteDTOPage = new PageImpl(noteDTOList, pageable, 0);
            return noteDTOPage;
        }

        List<Note> noteList = noteRepository.findAll(getWhereClauseFor(null, noteIdList));
        List<Note> newResult = new ArrayList<>();

        List<NoteDTO> noteDTOList = new ArrayList<NoteDTO>();
//        noteDTOList = addStatus(noteList, userId);

        //region开始进行分页
        int currIdx = (pageable.getPageNumber() > 0 ? pageable.getPageNumber() * pageable.getPageSize() : 0);
        for (int i = 0; i < pageable.getPageSize() && i < noteList.size() - currIdx; i++) {
            Note report = noteList.get(currIdx + i);
            newResult.add(report);
        }
        noteDTOList = addStatus(newResult, userId);
        for (NoteDTO dto: noteDTOList){
            String noteId = dto.getId();
            List<ScoreLogDTO> scoreLogDTOList = memberClient.findAllScoreByNoteId(noteId);
            log.info("查询评分列表返回结果:{}", scoreLogDTOList);
            if (scoreLogDTOList.size() > 0){
                for (ScoreLogDTO logDTO : scoreLogDTOList){
                    WhiskyDTO whiskyDTO = memberClient.findById(logDTO.getGoodId());
                    log.info("查询酒品详情返回结果:{}", whiskyDTO);
                    if (whiskyDTO != null){
                        logDTO.setWhiskyDTO(whiskyDTO);
                    }
                }
            }
            dto.setScoreLogDTOList(scoreLogDTOList);
        }
        Pageable pageable2 = new PageRequest(pageable.getPageNumber(), pageable.getPageSize());
        Page pageResult = new PageImpl(noteDTOList, pageable2, noteList.size());

        Page<NoteDTO> notePage = pageResult;

        return notePage;
        //endregion
    }

    /**
     * 我所有的帖子
     *
     * @param pageable
     * @param userId
     * @return
     */
    public Page<NoteDTO> getMyAllNotes(Pageable pageable, String userId) {
        List<Note> noteList = noteRepository.findAllNotes(userId);
        if (null == noteList) {
            List<NoteDTO> noteDTOList = new ArrayList<NoteDTO>();
            Page<NoteDTO> noteDTOPage = new PageImpl(noteDTOList, pageable, 0);
            return noteDTOPage;
        } else {
            List<NoteDTO> noteDTOList = new ArrayList<NoteDTO>();
            noteDTOList = addStatus(noteList, userId);

            List<Note> newResult = new ArrayList<>();
            //region开始进行分页
            int currIdx = (pageable.getPageNumber() > 0 ? pageable.getPageNumber() * pageable.getPageSize() : 0);
            for (int i = 0; i < pageable.getPageSize() && i < noteList.size() - currIdx; i++) {
                Note report = noteList.get(currIdx + i);
                newResult.add(report);
            }
            noteDTOList = addStatus(newResult, userId);
            for (NoteDTO dto: noteDTOList){
                String noteId = dto.getId();
                List<ScoreLogDTO> scoreLogDTOList = memberClient.findAllScoreByNoteId(noteId);
                log.info("查询评分列表返回结果:{}", scoreLogDTOList);
                if (scoreLogDTOList.size() > 0){
                    for (ScoreLogDTO logDTO : scoreLogDTOList){
                        WhiskyDTO whiskyDTO = memberClient.findById(logDTO.getGoodId());
                        log.info("查询酒品详情返回结果:{}", whiskyDTO);
                        if (whiskyDTO != null){
                            logDTO.setWhiskyDTO(whiskyDTO);
                        }
                    }
                }
                dto.setScoreLogDTOList(scoreLogDTOList);
            }
            Pageable pageable2 = new PageRequest(pageable.getPageNumber(), pageable.getPageSize());
            Page pageResult = new PageImpl(noteDTOList, pageable2, noteList.size());

            Page<NoteDTO> notePage = pageResult;

            return notePage;
            //endregion
        }
    }

    /**
     * 查询条件构建
     * 使用对象：我的发布、我的收藏、我的帖子(所有)
     *
     * @param stringList
     * @return
     */
    private Specification<Note> getWhereClauseFor(final NoteDTO noteDTO, List<String> stringList) {
        Specification<Note> specification = (Root<Note> root, CriteriaQuery<?> query,
                                             CriteriaBuilder cb) -> {
            List<Predicate> predicates = new ArrayList<Predicate>();
            Predicate lineFactoryLike = cb.equal(root.get("deleteStatus"), DeleteStatus.ACTIVATED);
            predicates.add(lineFactoryLike);
            if (null != stringList && stringList.size() >= 0) {
                CriteriaBuilder.In<String> in = cb.in(root.get("id"));
                for (String id : stringList) {
                    in.value(id);
                }
                predicates.add(in);
            }

            query.orderBy(cb.desc(root.get("createTime").as(ZonedDateTime.class)));
            Predicate[] ps = new Predicate[predicates.size()];
            return cb.and(predicates.toArray(ps));
        };
        return specification;
    }

    /**
     * 针对当前用户，增加用户与帖子之间的状态码，处理置顶
     *
     * @param noteList
     * @param unionId
     * @return
     */
    private List<NoteDTO> addStatus(List<Note> noteList, String unionId) {
        List<NoteDTO> noteDTOList = new ArrayList<NoteDTO>();
        List<NoteDTO> top = new ArrayList<>();
        for (Note note : noteList) {
            NoteDTO noteDTO = noteMapper.toDto(note);
            //是否关注了发帖人
            if (StringUtils.isNotEmpty(unionId) && StringUtils.isNotEmpty(noteDTO.getUserId())) {
                String userID = noteDTO.getUserId();
                log.info("unionId:{}-----userId:{}", unionId, userID);
                Relation relation = relationRepository.findOneByUserIdAndFollowId(unionId, userID);
                if (null != relation) {
                    noteDTO.setFollow(true);
                } else {
                    noteDTO.setFollow(false);
                }
            } else {
                noteDTO.setFollow(false);
            }
            //是否点赞了该帖
            if (StringUtils.isNotEmpty(unionId) && StringUtils.isNotEmpty(noteDTO.getId())) {
                String noteId = noteDTO.getId();
                NoteLikes noteLikes = noteLikesRepository.findOneByNoteIdAndUserId(noteId, unionId);
                if (null != noteLikes) {
                    noteDTO.setLike(true);
                } else {
                    noteDTO.setLike(false);
                }
            } else {
                noteDTO.setLike(false);
            }
//            //是否收藏了该帖
//            if (StringUtils.isNotEmpty(unionId) && StringUtils.isNotEmpty(noteDTO.getId())) {
//                String noteId = noteDTO.getId();
//                NoteCollection noteCollection = noteCollectionRepository.findOne(noteId, unionId);
//                if (null != noteCollection) {
//                    noteDTO.setCollect(true);
//                } else {
//                    noteDTO.setCollect(false);
//                }
//            } else {
//                noteDTO.setCollect(false);
//            }
            if (true == note.getTop()) {
                top.add(noteDTO);
            } else {
                noteDTOList.add(noteDTO);
            }
        }
        top.addAll(noteDTOList);
        return top;
    }

    private void addStatus2(Page<NoteDTO> noteList, String unionId) {
        if (StringUtils.isNotEmpty(unionId)) {
            List<String> followeIds = relationRepository.findFollowIdByUserId(unionId);
            List<String> likeIds = noteLikesRepository.findNoteIdsByUserId(unionId);

            for (NoteDTO noteDTO : noteList) {
                //是否关注了发帖人
                if (StringUtils.isNotEmpty(noteDTO.getUserId())) {
                    if (followeIds.contains(noteDTO.getUserId())) {
                        noteDTO.setFollow(true);
                    } else {
                        noteDTO.setFollow(false);
                    }
                } else {
                    noteDTO.setFollow(false);
                }

                //是否点赞了该帖
                if (StringUtils.isNotEmpty(noteDTO.getId())) {
                    if (likeIds.contains(noteDTO.getId())) {
                        noteDTO.setLike(true);
                    } else {
                        noteDTO.setLike(false);
                    }
                } else {
                    noteDTO.setLike(false);
                }
            }
        }
    }


    /**
     * 封禁帖子
     *
     * @param noteId
     * @return
     */
    public String banNote(String noteId) {
        Note note = noteRepository.findOne(noteId);
        if (null == note) {
            return "帖子不存在！";
        } else {
            if (AuditStatus.AUDITED == note.getAuditStatus()) {
                note.setAuditStatus(AuditStatus.UNAUDITED);
                noteRepository.save(note);
                return "封贴成功！";
            } else {
                return "该帖已被封禁！";
            }
        }
    }

    /**
     * 解封帖子
     *
     * @param noteId
     * @return
     */
    public String unBanNote(String noteId) {
        Note note = noteRepository.findOne(noteId);
        if (null == note) {
            return "帖子不存在！";
        } else {
            if (AuditStatus.UNAUDITED == note.getAuditStatus()) {
                note.setAuditStatus(AuditStatus.AUDITED);
                noteRepository.save(note);
                return "帖子解封成功！";
            } else {
                return "该帖未被封禁！";
            }
        }
    }

    /***
     * add by WangZhan
     * 20180806
     * 获取所有标签
     */
    public List<NoteTag> getAllNoteTags() {
        return noteTagRepository.findAll();
    }


    public List<NoteDTO> getNotesByWid(String wid) {
        List<Note> list = noteRepository.getNotesByWid(wid);
        List<NoteDTO> noteDTOList = new ArrayList<NoteDTO>();
        for (Note note : list) {
            noteDTOList.add(noteMapper.toDto(note));
        }
        return noteDTOList;
    }

    /**
     * 查询性能优化
     *
//     * @param lastIndex  分页参数：上次获取最小index
//     * @param pageSize   分页参数：请求条数
//     * @param keyWord    搜索栏的关键字
//     * @param columnType 分栏类型（0：所有 1：关注 2:精选）
//     * @param unionId    当前用户小程序的UnionID
     * @return
     */
    public Page<NoteDTO> homeForWechat(HomeVM vm) {
        log.info("homeForWechat.vm:{}", JSON.toJSONString(vm));
        List<String> stringList = null;
        Integer isRate = null;
        switch (vm.getColumnType()) {
            case 1:
                if (StringUtils.isNotEmpty(vm.getUnionId())) {
                    stringList = relationRepository.findFollowIdByUserId(vm.getUnionId());
                }
                break;
            case 2:
                isRate = 0;
                break;
        }
        log.info("homeForWechat.UnionIdList:{}", JSON.toJSONString(stringList));
        //region开始进行分页
        Pageable pageable = new PageRequest(Math.toIntExact(vm.getPage()), vm.getPageSize());
        Specification<Note> query = getHomeWhereClause4Wechat(vm.getPage(), vm.getKeyword(), stringList, vm.getTop(), isRate);
//        query.
        Page<Note> result = noteRepository.findAll(query, pageable);

        Page<NoteDTO> t = result.map(note -> noteMapper.toDto(note));
        for (NoteDTO dto : t){
            List<ScoreLogDTO> dtoList = memberClient.findAllScoreByNoteId(dto.getId());
            log.info("查询评分列表返回结果:{}", dtoList);
            if (dtoList.size() > 0){
                for (ScoreLogDTO logDTO : dtoList){
                    WhiskyDTO whiskyDTO = memberClient.findById(logDTO.getGoodId());
                    log.info("查询酒品详情返回结果:{}", whiskyDTO);
                    if (whiskyDTO != null){
                        logDTO.setWhiskyDTO(whiskyDTO);
                    }
                }
            }
            dto.setScoreLogDTOList(dtoList);
        }
        if (StringUtils.isNotEmpty(vm.getUnionId())) {
            addStatus2(t, vm.getUnionId());
        }
        return t;
    }

    /**
     * 动态生成查询条件
     *
     * @param lastIndex ----上次获取的最小index
     * @param keyWord ---关键字
     * @param userList ---用户（userId）列表
     * @param isRate
     * @return
     */
    private Specification<Note> getHomeWhereClause4Wechat(Long lastIndex, String keyWord, List<String> userList, Boolean isTop, Integer isRate) {
        Specification<Note> specification = (Root<Note> root, CriteriaQuery<?> query,
                                             CriteriaBuilder cb) -> {
            List<Predicate> predicates = new ArrayList<Predicate>();

            int isTopNum = 1;
            if (isTop) {
                isTopNum = 2;
            }
            Predicate isTopLess = cb.lessThan(root.get("isTop"), isTopNum);
            predicates.add(isTopLess);
//            if (lastIndex > 0) {
//                Predicate indexLike_add = cb.lessThan(root.get("createdIndex"), lastIndex);
//                predicates.add(indexLike_add);
//            }
            Predicate lineFactoryLike = cb.equal(root.get("deleteStatus"), DeleteStatus.ACTIVATED);
            Predicate lineFactoryEqual_add = cb.equal(root.get("auditStatus"), AuditStatus.AUDITED);
            predicates.add(lineFactoryEqual_add);
            predicates.add(lineFactoryLike);
            if (!CollectionUtils.isEmpty(userList)) {
                CriteriaBuilder.In<String> in = cb.in(root.get("userId"));
                for (String id : userList) {
                    in.value(id);
                }
                predicates.add(in);
            }
            if (StringUtils.isNotEmpty(keyWord)) {
                Expression<Integer> expression = cb.locate(root.get("searchContent"), keyWord);
                predicates.add(cb.greaterThan(expression, 0));
            }
            if (isRate != null) {
                Predicate rate = cb.equal(root.get("isRate"), true);
                predicates.add(rate);
            }
            List<Order> orderList = new ArrayList<Order>();
            orderList.add(cb.desc(root.get("isTop").as(Boolean.class)));
            orderList.add(cb.desc(root.get("createdIndex").as(Long.class)));
            query.orderBy(orderList);
            Predicate[] ps = new Predicate[predicates.size()];
            return cb.and(predicates.toArray(ps));
        };
        return specification;
    }

    public List<NoteDTO> findKeyWordList(String keyword, Integer page, Integer pageSize) {
        String key = allHomeNoteKey;
        List<NoteDTO> list;
        List<NoteDTO> result = new ArrayList<>();
        List<NoteDTO> resultList = new ArrayList<>();
        if (redisUtils.exists(key)){
            list = (List<NoteDTO>) redisUtils.get(key);
            result = getResultList(list, keyword);
            resultList = cutList(result, pageSize, page);
            return resultList;
        }
        List<Note> noteList = noteRepository.findAll();
        list = noteMapper.toDto(noteList);
        result = getResultList(list, keyword);
        resultList = cutList(result, pageSize, page);
        return resultList;
    }

    private List<NoteDTO> getResultList(List<NoteDTO> list, String keyword) {
        List<NoteDTO> result = new ArrayList<>();
        for (NoteDTO dto : list){
            if (dto.getTitle().contains(keyword) || dto.getContent().contains(keyword)
                || dto.getNickName().contains(keyword)) {
                result.add(dto);
            }
        }
        return result;
    }

    public List<NoteDTO> findAllForHome(Integer page, Integer pageSize) {
        String key = allHomeNoteKey;
        List<NoteDTO> list;
        List<NoteDTO> result;
        log.info("判断是否有缓存");
        if (redisUtils.exists(key)){
            log.info("有缓存");
            list = (List<NoteDTO>) redisUtils.get(key);
            log.info("取出缓存数据");
            result= cutList(list, pageSize, page);
            log.info("切割缓存,返回结果为:{}", JSON.toJSONString(result));
            return result;
        }
        log.info("没有缓存");
        List<Note> noteList = noteRepository.findAllNote();
        list = getScoreLog(noteList);
        redisUtils.set(key, list, ONE_DAY);
        result= cutList(list, pageSize, page);
        return result;
    }


    public List<NoteDTO> findUserFollow(String unionId, Integer page, Integer pageSize) {
        List<String> stringList = relationRepository.findFollowIdByUserId(unionId);
        List<Note> list = noteRepository.findByUserIdInOrderByIsTopDescUpdateTimeDesc(stringList);
        List<NoteDTO> dtoList = getScoreLog(list);
        List<NoteDTO> resultList= cutList(dtoList, pageSize, page);
        return resultList;
    }

    public List<NoteDTO> findFineList(Integer page, Integer pageSize) {
        String key = fineHomeNoteKey;
        List<NoteDTO> list;
        List<NoteDTO> result;
        log.info("判断是否有缓存");
        if (redisUtils.exists(key)){
            log.info("有缓存");
            list = (List<NoteDTO>) redisUtils.get(key);
            log.info("取出缓存数据");
            result = cutList(list, pageSize, page);
            log.info("切割缓存,返回结果为:{}", JSON.toJSONString(result));
            return result;
        }
        log.info("没有缓存");
        List<Note> noteList = noteRepository.findByIsRateOrderByIsTopDescUpdateTimeDesc(true);
        list = getScoreLog(noteList);
        redisUtils.set(key, list, ONE_DAY);
        result = cutList(list, pageSize, page);
        return result;
    }

    private List<NoteDTO> getScoreLog(List<Note> list){
        List<NoteDTO> dtoList = noteMapper.toDto(list);
        for (NoteDTO dto : dtoList){
            String noteId = dto.getId();
            List<ScoreLogDTO> scoreLogDTOList = memberClient.findAllScoreByNoteId(noteId);
            log.info("查询评分列表返回结果:{}", scoreLogDTOList);
            if (dtoList.size() > 0){
                for (ScoreLogDTO logDTO : scoreLogDTOList){
                    WhiskyDTO whiskyDTO = memberClient.findById(logDTO.getGoodId());
                    log.info("查询酒品详情返回结果:{}", whiskyDTO);
                    if (whiskyDTO != null){
                        logDTO.setWhiskyDTO(whiskyDTO);
                    }
                }
            }
            dto.setScoreLogDTOList(scoreLogDTOList);
        }
        return dtoList;
    }

    private List<NoteDTO> cutList(List<NoteDTO> list, Integer pageSize, Integer page){
        Integer pageEnd = pageSize * (page + 1);
        if (list.size() < pageEnd) {
            pageEnd = list.size();
        }
        Integer pageFirst =  pageSize * page;
        if(pageFirst>list.size()){
            return new ArrayList<>() ;
        }
        List<NoteDTO> resultList= list.subList(pageFirst, pageEnd);
        return resultList;
    }

    public void recommend(QueryIdVM vm) {
        Note note = noteRepository.findOne(vm.getId());
        if (!note.getTop()){
            note.setTop(true);
        }else if(note.getTop()){
            note.setTop(false);
        }
        Note result = noteRepository.save(note);
//        noteCache.refreshHomeCache();
//        noteCache.re();
//        noteCache.refreshHomeCache();

    }

    public String testRedis(String key) {
        if (redisUtils.exists(key)){
            log.info("redis取出的数据:{}", redisUtils.get(key));
            return "有缓存";
        }
        return "没缓存";
    }

    public List<NoteDTO> getCommentById(GoodIdVM vm) {
        List<String> noteIdlist = memberClient.findNoteIdByGoodsId(vm.getGoodId());
        List<NoteDTO> dtoList = new ArrayList<>();
        if (noteIdlist.size() > 0) {
            List<Note> noteList = noteRepository.findByIds(noteIdlist);
            for (Note note : noteList) {
                NoteDTO dto = noteMapper.toDto(note);
                List<ScoreLogDTO> logDTO = memberClient.findAllScoreByNoteId(dto.getId());
                if (logDTO.size() > 0){
                    for (ScoreLogDTO scoreLogDTO : logDTO){
                        WhiskyDTO dto1 = memberClient.findById(scoreLogDTO.getGoodId());
                        scoreLogDTO.setWhiskyDTO(dto1);
                    }
                    dto.setScoreLogDTOList(logDTO);
                }
                dtoList.add(dto);
            }
        }
        return dtoList;
    }

    public void isTop(QueryIdVM vm) {
        Note note = noteRepository.findOne(vm.getId());
        log.info("note:{}", JSON.toJSONString(note));
        if (note != null){
            if (note.getAuditStatus() == AuditStatus.AUDITED && note.getDeleteStatus() == DeleteStatus.ACTIVATED){
                if (note.getTop()){
                    note.setTop(false);
                }else {
                    note.setTop(true);
                }
                note.setUpdateTime(ZonedDateTime.now());
                Note result = noteRepository.save(note);
            }
        }
    }

    @Scheduled(cron = "0 0 1 * * ?")
    public void refreshSearchContent(){
        List<Note> noteList = noteRepository.findAll();
        for (Note note : noteList){
            String searchContent = null;
            log.debug("Request to save {} : {}", getEntityName(), note);
            UnionIdVM unionIdVM = new UnionIdVM();
            unionIdVM.setUnionId(note.getUserId());
            log.info("unionId:{}", unionIdVM.getUnionId());
            Member member = memberClient.findMemberByUserId(unionIdVM);
            String memberName = member.getNickName();
            searchContent = memberName;
            String noteContent = note.getContent();
            searchContent = searchContent + "," + noteContent;
            List<ScoreLogDTO> logDTOList = memberClient.findAllScoreByNoteId(note.getId());
            String goodName = "";
            for (ScoreLogDTO logDTO : logDTOList){
                WhiskyDTO dto = memberClient.findById(logDTO.getGoodId());
                goodName = goodName + "," + dto.getNameCh();
            }
            if (StringUtils.isNotEmpty(goodName)) {
                searchContent = searchContent + "," + goodName;
            }
            note.setSearchContent(searchContent);
            note = noteRepository.save(note);
            noteRepository.save(note);
        }
    }

    public void changeIsRate(String id) {
        Note note = noteRepository.findOne(id);
        if (note.getRate() == null || note.getRate() == false){
            note.setRate(true);
        }else {
            note.setRate(false);
        }
        note.setUpdateTime(ZonedDateTime.now());
        noteRepository.save(note);
    }
}
